/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2023-11-14     ganze       the first version
 */

/*
 * 关于 rt_hw_sensor_register中flag参数与后续工作模式的说明

 * 在sensor.c的rt_hw_sensor_register函数设置设备dev（传感器）的flag
 * 在sensor.c的rt_sensor_open函数，对打开标签oflag进行判断：
 *
 * 假如 oflag & RT_DEVICE_FLAG_RDONLY && dev->flag & RT_DEVICE_FLAG_RDONLY成立
 * 则RT-Thread将传感器工作状态置为轮询模式 ---- RT_SENSOR_MODE_POLLING
 *
 * 假如 oflag & RT_DEVICE_FLAG_INT_RX && dev->flag & RT_DEVICE_FLAG_INT_RX成立
 * 则RT-Thread将传感器工作状态置为中断模式 ---- RT_SENSOR_MODE_INT
 *
 * 假如 oflag & RT_DEVICE_FLAG_FIFO_RX && dev->flag & RT_DEVICE_FLAG_FIFO_RX成立
 * 则RT-Thread将传感器工作状态置为中断FIFO模式 ---- RT_SENSOR_MODE_FIFO
 *
 * 对于以上3种模式，sensor.c在 rt_sensor_cb 做了区分，具体逻辑如下：
 *
 * 1）传感器本身触发中断，发出中断信号
 * 2）MCU绑定信号引脚检测中断，调用irq_callback函数
 * 3）irq_callback函数调用rt_sensor_cb函数
 * 4）rt_sensor_cb函数首先判断sen->parent.rx_indicate == RT_NULL如果成立则结束
 * 5）然后sen->irq_handle != RT_NULL成立则调用sen->irq_handle(sen)，此为用户设置的中断回调函数
 * 6）如果sen->data_len > 0则调用rx_indicate读取所有data_buf数据
 * 7）如果传感器工作状态置为中断模式，则调用rx_indicate读取一个完整的rt_sensor_data
 * 8）如果传感器工作状态置为FIFO中断模式，则调用rx_indicate读取fifo_max个完整的rt_sensor_data
 *
 * 至此可以这么理解：检测到一次中断，对于RT_SENSOR_MODE_INT工作模式则读取一个sensor_data到传感器的data_buf
 * 对于RT_SENSOR_MODE_FIFO工作模式则读取fifo_max个sensor_data到传感器的data_buf
 * 但是令人不解的是rt_sensor_cb中，在区分RT_SENSOR_MODE_INT和RT_SENSOR_MODE_FIFO之前有如下语句
 * if (sen->data_len > 0)
 *  {
 *     sen->parent.rx_indicate(&sen->parent, sen->data_len / sizeof(struct rt_sensor_data));
 *  }
 *  此语句的含义是当已知data_len>0则读取尽可能多的rt_sensor_data到传感器的data_buf中
 *  有一个问题，传感器在触发中断的时候，MCU也许只是检测到一个中断信号，并不知道data_len是多少
 *  除非传感器自动向MCU输出字节
 *  本文专注于bmi270设备，经过查阅数据手册并没有发现bmi270能够自动输出传感器数据
 *  因此sen->data_len > 0不成立，即根据7）和8）步骤进行
 *
 *  但是需要注意sensor.c中rt_hw_sensor_register函数在注册传感器时，默认rx_indicate=RT_NULL
 *  因此默认情况下，即使发生了中断，也不会调用rx_indicate去读取
 *  要想在RT_SENSOR_MODE_INT或者RT_SENSOR_MODE_FIFO模式下，RT-Thread能够自动读取传感器数据到指定buf
 *  则需要用户自己创建rx_indicate函数。
 *
 *  最后，根据以上分析，结合bmi270这款IMU特性，令其工作在轮询模式下，
 *  但是提供工作在FIFO中断模式选项，FIFO中断对应是FIFO的watermark中断
 *  只要watermark中断发生，且工作在FIFO中断模式，则读取1个完整的FIFO帧
 *  并解析此FIFO帧
 *
 *  本驱动不提供RT_SENSOR_MODE_INT工作选项，但是可以指定某些FEATURE发生时触发中断
 *  然后用户可以遍历中断寄存器去查看哪个中断触发了，例如静止中断或者计步器中断
 *
 *
 */

/*
 * BMI270数据手册对于SPI协议的读写有如下说明：
 *
 * 通过SDO线从设备接收到的第一个字节对应于一个虚拟字节，
 * 第二个字节对应于从指定的寄存器地址读出的值。这意味着，对于一个基本的
 * 读取操作，必须读取两个字节，必须删除第一个字节，并且必须解释第二个字节。
 *
 * 当主机想要向bmi270写入寄存器地址数据时，需注意发送寄存器地址最高位为0
 * 当主机想要从bmi270获取寄存器存储的值时，需注意发送寄存器地址最高位为1
 *
 * 如果想要向bmi270寄存器写入一个字节数据：
 * 1）发送寄存器地址，注意最高位为0
 * 2）写入字节
 *
 * 如果想要从bmi270寄存器读出一个字节数据：
 * 1）发送寄存器地址，注意最高位为1
 * 2）读寄存器2个字节，将第二个读出的字节作为寄存器的内容，忽略第一个字节
 *
 * 如果想要从bmi270寄存器连续读出多个字节数据：
 * 1）发送初始寄存器地址，注意最高位为1
 * 2）保持CSB低，连续读字节，第一个读出的字节无效，将第2个字节视为第一个字节，依此类推
 *
 */

#include <rtdbg.h>
#include <drv_spi.h>
#include <drivers/i2c.h>
#include <drv_soft_i2c.h>
#include <drivers/pin.h>
#include <drivers/spi.h>
#include "sensor_bmi270.h"
#include "sensor/read_sensor.h"

#define DBG_ENABLE
// #define DBG_LEVEL DBG_LOG
// #define DBG_SECTION_NAME "sensor.bosch.bmi270"
#define DBG_COLOR

static uint8_t sense_list[] = {
#ifdef BMI270_USING_ACCE
    BMI2_ACCEL,
#endif
#ifdef BMI270_USING_GYRO
    BMI2_GYRO,
#endif
#ifdef BMI270_USING_AUX
    BMI2_AUX,
#endif
#ifdef BMI270_USING_TEMP
    BMI2_TEMP
#endif
};

static struct rt_spi_device *bmi270_spi_dev = RT_NULL;
static struct rt_i2c_bus_device *bmi270_i2c_bus = RT_NULL;

static struct bmi2_sens_config acce_init_cfg;
static struct bmi2_sens_config gyro_init_cfg;

/// @brief 根据32bit的range映射到枚举类型QMC5883_Range
static uint8_t
find_bmi270_range(uint8_t sensor_type, rt_uint32_t rt_range);

/// @brief 根据32bit的range映射到枚举类型QMC5883_odr
static uint8_t find_bmi270_odr(uint8_t sensor_type, rt_uint16_t rt_odr);

/// @brief 该函数向bmi270官方驱动提供延时接口
/// @param period 延时us时长
/// @return
static void bmi270_delay_us(uint32_t period, void *intf_ptr);

/// @brief 该函数向bmi270官方驱动提供延时接口
/// @param period 延时ms时长
/// @return
static void bmi270_delay_ms(uint32_t period, void *intf_ptr);

/// @brief 该函数向bmi270官方驱动提供以SPI方式读取寄存器接口
/// @param bus RT-Thread中SPI或者I2C总线
/// @param addr 传感器的I2C协议地址-在SPI协议中无效
/// @param reg 寄存器地址
/// @param data_buf 保存读取寄存器的数据
/// @param data_len 指定读取长度
/// @return 读取成功RT_EOK ,失败 RT_EFAIL
static int8_t bmi270_spi_read_reg(uint8_t reg_addr, uint8_t *data_buf, uint32_t data_len, void *intf_ptr);

/// @brief 该函数向bmi270官方驱动提供以SPI方式写入寄存器接口
/// @param bus RT-Thread中SPI或者I2C总线
/// @param addr 传感器的I2C协议地址-在SPI协议中无效
/// @param reg 寄存器地址
/// @param data_buf 保存写入寄存器的数据
/// @param data_len 指定写入长度
/// @return 写入成功或者失败
static int8_t bmi270_spi_write_reg(uint8_t reg_addr, const uint8_t *data_buf, uint32_t data_len, void *intf_ptr);

/// @brief 该函数向bmi270官方驱动提供以I2C方式读取寄存器接口
/// @param bus RT-Thread中SPI或者I2C总线
/// @param addr 传感器的I2C协议地址-在SPI协议中无效
/// @param reg 寄存器地址
/// @param data_buf 保存读取寄存器的数据
/// @param data_len 指定读取长度
/// @return 读取成功RT_EOK ,失败 RT_EFAIL
static int8_t bmi270_i2c_read_reg(uint8_t reg_addr, uint8_t *data_buf, uint32_t data_len, void *intf_ptr);

/// @brief 该函数向bmi270官方驱动提供以I2C方式写入寄存器接口
/// @param bus RT-Thread中SPI或者I2C总线
/// @param addr 传感器的I2C协议地址-在SPI协议中无效
/// @param reg 寄存器地址
/// @param data_buf 保存写入寄存器的数据
/// @param data_len 指定写入长度
/// @return 写入成功或者失败
static int8_t bmi270_i2c_write_reg(uint8_t reg_addr, const uint8_t *data_buf, uint32_t data_len, void *intf_ptr);

/// @brief 手动命令bmi270读取从设备数据
/// @param dev
/// @param aux_id
/// @param reg_addr
/// @param aux_data_buf
/// @param data_len
/// @return
// static int8_t bmi270_read_aux_manual_mode(void *dev, uint8_t aux_id, uint8_t reg_addr, uint8_t *aux_data_buf, uint16_t data_len);

/// @brief 手动命令bmi270向从设备数据写入数据
/// @param dev
/// @param aux_id
/// @param reg_addr
/// @param aux_data_buf
/// @param data_len
/// @return
// static int8_t bmi270_write_aux_manual_mode(void *dev, uint8_t aux_id, uint8_t reg_addr, uint8_t *aux_data_buf, uint16_t data_len);

/// @brief 初始创建bmi270设备时，分别设置加速度和陀螺仪的参数
/// @param acce_init_cfg
/// @param gyro_init_cfg
/// @param hdev
/// @return
static int8_t bmi270_set_acce_gyr_init_config(
    struct bmi2_sens_config *acce_init_cfg,
    struct bmi2_sens_config *gyro_init_cfg,
    struct bmi2_dev *hdev);

/// @brief 当使用I2C协议时创建bmi270设备
/// @param intf
/// @return
static struct bmi2_dev *bmi270_create_i2c(struct rt_sensor_intf *intf);

/// @brief 当使用SPI协议时创建bmi270设备
/// @param intf
/// @return
static struct bmi2_dev *bmi270_create_spi(struct rt_sensor_intf *intf);

/// @brief 创建bmi270设备
/// @param intf 传感器接口
/// @return
static struct bmi2_dev *bmi270_create(struct rt_sensor_intf *intf);

/// @brief bmi270使用SPI协议时挂载总线
/// @param
/// @return
static int bmi270_attach_spi_bus(void);

/// @brief 向RT-Thread提供控制bmi270接口函数，根据不同命令使bmi270做出不同反应
/// @param sensor bmi270设备
/// @param cmd 命令字
/// @param args 参数
/// @return
static rt_err_t bmi270_control(struct rt_sensor_device *sensor, int cmd, void *args);

/// @brief 向RT-Thread提供读取bmi270传感数据接口函数
/// @param sensor bmi270设备
/// @param buf 存储地址
/// @param len 读取长度
/// @return
static rt_size_t bmi270_fetch_data(struct rt_sensor_device *sensor, void *buf, rt_size_t len);

/// @brief 从FIFO中获取加速度、陀螺仪、温度数据
/// @param sensor
/// @param buf
/// @param len
/// @return
static int8_t bmi270_read_fifo(struct rt_sensor_device *sensor, void *buf, rt_size_t len);

/// @brief 不从FIFO中获取加速度、陀螺仪、温度数据，而是直接读取
/// @param sensor
/// @param buf
/// @param len
/// @return
static int8_t bmi270_read(struct rt_sensor_device *sensor, struct rt_sensor_data *buf, rt_size_t len);

/// @brief
/// @param dst
/// @param src
/// @return
static int8_t bmi270_copy2_rtthread(struct rt_sensor_data *dst, struct bmi2_sens_data *src);

/// @brief bmi270向RT-Thread注册陀螺仪传感器设备
/// @param cfg
/// @param hdev
/// @return
static int8_t bmi270_sensor_register_gyro(struct rt_sensor_config *cfg, void *hdev);

/// @brief bmi270向RT-Thread注册加速度传感器设备
/// @param cfg
/// @param hdev
/// @return
static int8_t bmi270_sensor_register_acce(struct rt_sensor_config *cfg, void *hdev);

/// @brief bmi270向RT-Thread注册温度传感器设备
/// @param cfg
/// @param hdev
/// @return
static int8_t bmi270_sensor_register_temp(struct rt_sensor_config *cfg, void *hdev);

/// @brief bmi270向RT-Thread注册传感器设备
/// @param cfg
/// @param dev bmi270设备
/// @return
static int8_t bmi270_sensor_register(struct rt_sensor_config *cfg, void *hdev);

/// @brief bmi270设置加速度传感器或者陀螺仪的ODR
/// @param sensor 传感器
/// @param odr ODR 对于加速度，则从 BMI2_ACC_ODR_0_78HZ ~ BMI2_ACC_ODR_1600HZ选取，
///            对于陀螺仪从 BMI2_GYR_ODR_25HZ ~ BMI2_GYR_ODR_3200HZ
///            对于辅助设备从 BMI2_AUX_ODR_0_78HZ ~ BMI2_AUX_ODR_800HZ
/// @return
static int8_t bmi270_set_odr(rt_sensor_t sensor, rt_uint16_t odr);

/// @brief bmi270设置加速度传感器或者陀螺仪的测量范围
/// @param sensor 传感器
/// @param range 范围
/// @return
static int8_t bmi270_set_range(rt_sensor_t sensor, rt_uint16_t range);

/// @brief bmi270设置加速度传感器或者陀螺仪功耗
/// @param sensor
/// @param pwr_mode
/// @return
static int8_t bmi270_set_pwr_mode(rt_sensor_t sensor, rt_uint8_t pwr_mode);

/// @brief bmi270选择工作模式，中断模式或者是FIFO模式或者是轮询方式
/// @param sensor
/// @param rx_mode
/// @return
static int8_t bmi270_select_mode(rt_sensor_t sensor, rt_uint8_t rx_mode);

/// @brief bmi270自检
/// @param sensor
/// @param nones
/// @return
static int8_t bmi270_self_test(rt_sensor_t sensor, rt_uint8_t none);

/// @brief
/// @param sensor_data [out] 经过分辨率转换得到的实际传感器数据
/// @param digital_num [in] 传感器寄存器存储测量数据
/// @param resolution [in] 分辨率
/// @param sensor_type [in] 传感器类型
/// @return
static int8_t sensor_data_from_digital_num(int32_t *sensor_data, int32_t digital_num, float resolution, uint8_t sensor_type);

/// @brief 根据bmi270温度寄存器的16bit数据，得到实际温度并按照RT-Thread要求存储
/// @param sensor_data
/// @param digital_num
/// @return
static int8_t bmi270_temp_from_digital_num(int32_t *sensor_data, uint16_t digital_num);

/// @brief 辅助设备接口函数指针组成的结构体
static aux_ctrl_fcn sg_aux_ctrl_fcn;

/// @brief 此函数用于初始化bmi270设备
/// @param cfg RT-Thread上定义传感器配置
/// @param aux_create_init 从设备创建与初始化函数
/// @return
static int8_t rt_hw_bmi270_init(struct rt_sensor_config *cfg, aux_ctrl_fcn aux_ctrl);

static int8_t rt_hw_bmi270_init(struct rt_sensor_config *cfg, aux_ctrl_fcn aux_ctrl)
{
    int8_t rslt = RT_EOK;
    struct bmi2_dev *hdev = RT_NULL;

    rt_kprintf("bmi270 sensor start create \n");

    /* step1 : create bmi270 device */
    hdev = bmi270_create(&cfg->intf);
    if (hdev == RT_NULL)
    {
        rt_kprintf("bmi270 sensor create failed \n");
        return RT_ERROR;
    }

    /* step2 : call aux create callback function, create and init aux device */
    sg_aux_ctrl_fcn = aux_ctrl;
    if (aux_ctrl._aux_create_ptr_ != RT_NULL)
    {
        rslt = (aux_ctrl._aux_create_ptr_)(hdev);
        if (rslt != RT_EOK)
        {
            rt_kprintf("bmi270 aux device create failed \n");
        }
    }

    /* step3 : regist bmi270 sensor into RT-Thread sensor driver */
    rslt = bmi270_sensor_register(cfg, hdev);
    if (rslt != RT_EOK)
    {
        rt_kprintf("bmi270 sensor register failed \n");
        return RT_ERROR;
    }
    return RT_EOK;
}

int rt_start_bmi270_app(void)
{
    struct rt_sensor_config cfg;
    cfg.intf.dev_name = BMI270_SPI_DEVNAME;
    cfg.intf.user_data = (void *)(0x69);
    cfg.intf.type = RT_SENSOR_INTF_SPI;
    cfg.irq_pin.pin = RT_PIN_NONE;

    aux_ctrl_fcn aux_ctrl;
    aux_ctrl._aux_create_ptr_ = RT_NULL;
    aux_ctrl._bmi270_sensor_register_aux_ = RT_NULL;
    rt_hw_bmi270_init(&cfg, aux_ctrl);

    rt_thread_mdelay(10);
    return RT_EOK;
}
INIT_APP_EXPORT(rt_start_bmi270_app);

static rt_uint8_t find_bmi270_range(rt_uint8_t sensor_type, rt_uint32_t rt_range)
{
    rt_uint8_t range = 0;
    switch (sensor_type)
    {
    case RT_SENSOR_CLASS_ACCE:
        if (rt_range <= 2000)
            range = BMI2_ACC_RANGE_2G;
        else if (rt_range <= 4000)
            range = BMI2_ACC_RANGE_4G;
        else if (rt_range <= 8000)
            range = BMI2_ACC_RANGE_8G;
        else
            range = BMI2_ACC_RANGE_16G;
        break;

    case RT_SENSOR_CLASS_GYRO:
        if (rt_range <= 125000)
            range = BMI2_GYR_RANGE_125;
        else if (rt_range <= 250000)
            range = BMI2_GYR_RANGE_250;
        else if (rt_range <= 500000)
            range = BMI2_GYR_RANGE_500;
        else if (rt_range <= 1000000)
            range = BMI2_GYR_RANGE_1000;
        else
            range = BMI2_GYR_RANGE_2000;
        break;
    default:
        break;
    }

    return range;
}

static uint8_t find_bmi270_odr(uint8_t sensor_type, rt_uint16_t rt_odr)
{
    rt_uint8_t odr = 0;
    switch (sensor_type)
    {
    case RT_SENSOR_CLASS_ACCE:
        if (rt_odr <= 1)
            odr = BMI2_ACC_ODR_0_78HZ;
        else if (rt_odr <= 2)
            odr = BMI2_ACC_ODR_1_56HZ;
        else if (rt_odr <= 4)
            odr = BMI2_ACC_ODR_3_12HZ;
        else if (rt_odr <= 7)
            odr = BMI2_ACC_ODR_6_25HZ;
        else if (rt_odr <= 15)
            odr = BMI2_ACC_ODR_12_5HZ;
        else if (rt_odr <= 25)
            odr = BMI2_ACC_ODR_25HZ;
        else if (rt_odr <= 50)
            odr = BMI2_ACC_ODR_50HZ;
        else if (rt_odr <= 100)
            odr = BMI2_ACC_ODR_100HZ;
        else if (rt_odr <= 200)
            odr = BMI2_ACC_ODR_200HZ;
        else if (rt_odr <= 400)
            odr = BMI2_ACC_ODR_400HZ;
        else if (rt_odr <= 800)
            odr = BMI2_ACC_ODR_800HZ;
        else
            odr = BMI2_ACC_ODR_1600HZ;
        break;

    case RT_SENSOR_CLASS_GYRO:
        if (rt_odr <= 25)
            odr = BMI2_GYR_ODR_25HZ;
        else if (rt_odr <= 50)
            odr = BMI2_GYR_ODR_50HZ;
        else if (rt_odr <= 100)
            odr = BMI2_GYR_ODR_100HZ;
        else if (rt_odr <= 200)
            odr = BMI2_GYR_ODR_200HZ;
        else if (rt_odr <= 400)
            odr = BMI2_GYR_ODR_400HZ;
        else if (rt_odr <= 800)
            odr = BMI2_GYR_ODR_800HZ;
        else
            odr = BMI2_GYR_ODR_1600HZ;
        break;

    case RT_SENSOR_CLASS_MAG:
        if (rt_odr <= 25)
            odr = BMI2_AUX_ODR_25HZ;
        else if (rt_odr <= 50)
            odr = BMI2_AUX_ODR_50HZ;
        else if (rt_odr <= 100)
            odr = BMI2_AUX_ODR_100HZ;
        else if (rt_odr <= 200)
            odr = BMI2_AUX_ODR_200HZ;
        else if (rt_odr <= 400)
            odr = BMI2_AUX_ODR_400HZ;
        else
            odr = BMI2_AUX_ODR_800HZ;
        break;
    default:
        break;
    }

    return odr;
}

static void bmi270_delay_us(uint32_t period, void *intf_ptr)
{
    if (period <= 1000)
    {
        bmi270_delay_ms(1, intf_ptr);
    }
    else
    {
        bmi270_delay_ms(period / 1000, intf_ptr);
    }
}

static void bmi270_delay_ms(uint32_t period, void *intf_ptr)
{
    rt_thread_mdelay(period);
}

static int8_t bmi270_spi_read_reg(uint8_t reg_addr, uint8_t *data_buf, uint32_t data_len, void *intf_ptr)
{
    if (bmi270_spi_dev == RT_NULL)
    {
        rt_kprintf("bmi270_spi_dev == RT_NULL \n");
        return BMI2_E_COM_FAIL;
    }

    rt_err_t read_result = rt_spi_send_then_recv(bmi270_spi_dev, &reg_addr, 1, data_buf, data_len);
    return (int8_t)read_result;

    return RT_EOK;
}

static int8_t bmi270_spi_write_reg(uint8_t reg_addr, const uint8_t *data_buf, uint32_t data_len, void *intf_ptr)
{
    if (bmi270_spi_dev == RT_NULL)
    {
        rt_kprintf("bmi270_spi_dev == RT_NULL \n");
        return BMI2_E_COM_FAIL;
    }

    rt_err_t write_result = rt_spi_send_then_send(bmi270_spi_dev, &reg_addr, 1, data_buf, data_len);
    return (int8_t)write_result;
}

/* uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr */
static int8_t bmi270_i2c_read_reg(uint8_t reg_addr, uint8_t *data_buf, uint32_t data_len, void *intf_ptr)
{
    if (bmi270_i2c_bus == RT_NULL)
    {
        rt_kprintf("bmi270_i2c_bus == RT_NULL \n");
        return BMI2_E_COM_FAIL;
    }

    rt_uint8_t tmp = reg_addr;
    struct rt_i2c_msg msgs[2];

    msgs[0].addr = BMI270_I2C_ADDR; /* Slave address */
    msgs[0].flags = RT_I2C_WR;      /* Write flag */
    msgs[0].buf = &tmp;             /* Slave register address */
    msgs[0].len = 1;                /* Number of bytes sent */

    msgs[1].addr = BMI270_I2C_ADDR; /* Slave address */
    msgs[1].flags = RT_I2C_RD;      /* Read flag */
    msgs[1].buf = data_buf;         /* Read data pointer */
    msgs[1].len = data_len;         /* Number of bytes read */

    if (rt_i2c_transfer(bmi270_i2c_bus, msgs, 2) != 2)
    {
        return -RT_ERROR;
    }

    return RT_EOK;
}

static int8_t bmi270_i2c_write_reg(uint8_t reg_addr, const uint8_t *data_buf, uint32_t data_len, void *intf_ptr)
{
    if (bmi270_i2c_bus == RT_NULL)
    {
        rt_kprintf("bmi270_i2c_bus == RT_NULL \n");
        return BMI2_E_COM_FAIL;
    }

    rt_uint8_t tmp = reg_addr;
    struct rt_i2c_msg msgs[2];

    msgs[0].addr = BMI270_I2C_ADDR; /* Slave address */
    msgs[0].flags = RT_I2C_WR;      /* Write flag */
    msgs[0].buf = &tmp;             /* Slave register address */
    msgs[0].len = 1;                /* Number of bytes sent */

    msgs[1].addr = BMI270_I2C_ADDR;              /* Slave address */
    msgs[1].flags = RT_I2C_WR | RT_I2C_NO_START; /* Read flag */
    msgs[1].buf = (uint8_t *)data_buf;           /* Read data pointer */
    msgs[1].len = data_len;                      /* Number of bytes read */

    if (rt_i2c_transfer(bmi270_i2c_bus, msgs, 2) != 2)
    {
        return -RT_ERROR;
    }

    return RT_EOK;
}

static int8_t bmi270_set_acce_gyr_init_config(
    struct bmi2_sens_config *acce_init_cfg,
    struct bmi2_sens_config *gyro_init_cfg,
    struct bmi2_dev *hdev)
{
    /* Bosch官方API bmi270_init函数调用了bmi2_write_config_file
       写入bmi270配置文件暂时没有资料表明bmi270官方的配置文件含义
       因此，在bmi270_init之后调用此函数按照预定设计配置bmi270的加速度
       和陀螺仪的ODR、范围等特性
    */
    int8_t rslt = RT_EOK;

    if (acce_init_cfg == RT_NULL || gyro_init_cfg == RT_NULL || hdev == RT_NULL)
    {
        rt_kprintf("bmi270_set_acce_gyr_init_config null pointer\n");
        return RT_ERROR;
    }

    acce_init_cfg->type = BMI2_ACCEL;
    acce_init_cfg->cfg.acc.odr = BMI2_ACC_ODR_100HZ;
    acce_init_cfg->cfg.acc.bwp = BMI2_ACC_NORMAL_AVG4;
    acce_init_cfg->cfg.acc.filter_perf = BMI2_ENABLE;
    acce_init_cfg->cfg.acc.range = BMI2_ACC_RANGE_8G; /* 这里设置加速度范围8g，那么参照数据手册分辨率为4096LSB/g */
    rslt = bmi270_set_sensor_config(acce_init_cfg, 1, hdev);
    if (rslt != RT_EOK)
    {
        rt_kprintf("bmi270_create--->bmi270_set_sensor_config-->acce failed\n");
    }

    gyro_init_cfg->type = BMI2_GYRO;
    gyro_init_cfg->cfg.gyr.bwp = BMI2_GYR_NORMAL_MODE;
    gyro_init_cfg->cfg.gyr.filter_perf = BMI2_ENABLE;
    gyro_init_cfg->cfg.gyr.odr = BMI2_GYR_ODR_800HZ;
    gyro_init_cfg->cfg.gyr.noise_perf = BMI2_ENABLE;
    gyro_init_cfg->cfg.gyr.ois_range = BMI2_GYR_OIS_250;
    gyro_init_cfg->cfg.gyr.range = BMI2_GYR_RANGE_1000; /* 这里设置陀螺仪范围1000dps，那么参照数据手册分辨率为32.768LSB/dps */
    rslt = bmi270_set_sensor_config(gyro_init_cfg, 1, hdev);
    if (rslt != RT_EOK)
    {
        rt_kprintf("bmi270_create--->bmi270_set_sensor_config-->gyro failed\n");
    }

    return rslt;
}

static struct bmi2_dev *bmi270_create_i2c(struct rt_sensor_intf *intf)
{
    struct bmi2_dev *hdev = RT_NULL;

    bmi270_i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(intf->dev_name);
    if (bmi270_i2c_bus == RT_NULL)
    {
        rt_kprintf("can not find device %s", intf->dev_name);
        return RT_NULL;
    }

    hdev = rt_calloc(1, sizeof(struct bmi2_dev));
    if (hdev == RT_NULL)
    {
        rt_kprintf("bmi270 dev memory allocation failed");
        return RT_NULL;
    }

    /* BMI160 I2C device address */
    hdev->intf = BMI2_I2C_INTF;
    hdev->read = bmi270_i2c_read_reg;
    hdev->write = bmi270_i2c_write_reg;
    hdev->delay_us = bmi270_delay_us;

    return hdev;
}

static struct bmi2_dev *bmi270_create_spi(struct rt_sensor_intf *intf)
{
    struct bmi2_dev *hdev = RT_NULL;
    struct rt_spi_device *spi_dev = RT_NULL;

    rt_kprintf("start find device %s \n", intf->dev_name);
    spi_dev = (struct rt_spi_device *)rt_device_find(intf->dev_name);
    if (spi_dev == RT_NULL)
    {
        rt_kprintf("can not find device %s \n", intf->dev_name);
        return RT_NULL;
    }
    rt_kprintf("find device %s success\n", intf->dev_name);
    bmi270_spi_dev = spi_dev;

    // 配置SPI传输参数
    struct rt_spi_configuration cfg;
    cfg.data_width = 8;
    cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB;
    cfg.max_hz = 10 * 1000 * 1000; /* 10M */

    if (rt_spi_configure(spi_dev, &cfg) != RT_EOK)
    {
        rt_kprintf("bmi270 config spi failed\n");
        return RT_NULL;
    }
    rt_kprintf("bmi270 config spi success\n");

    hdev = rt_calloc(1, sizeof(struct bmi2_dev));
    if (hdev == RT_NULL)
    {
        rt_kprintf("bmi270 dev memory allocation failed\n");
        return RT_NULL;
    }

    hdev->intf = BMI2_SPI_INTF;
    hdev->read = bmi270_spi_read_reg;
    hdev->write = bmi270_spi_write_reg;
    hdev->delay_us = bmi270_delay_us;

    return hdev;
}

static struct bmi2_dev *bmi270_create(struct rt_sensor_intf *intf)
{
    int8_t rslt = RT_EOK;

    struct bmi2_dev *hdev = RT_NULL;

    /* create bmi270 device */
    if (intf->type == RT_SENSOR_INTF_I2C)
    {
        hdev = bmi270_create_i2c(intf);
    }
    else if (intf->type == RT_SENSOR_INTF_SPI)
    {
        hdev = bmi270_create_spi(intf);
    }
    else
    {
        rt_kprintf("bmi270 intface type error: %d\n", intf->type);
        return RT_NULL;
    }

    rt_kprintf("start bmi270 init\n");

    /* initialize bmi270 device */
    rslt = bmi270_init(hdev);
    if (rslt != BMI2_OK)
    {
        rt_kprintf("bmi270 init failed\n");
        return RT_NULL;
    }
    rt_kprintf("bmi270 init success\n");

    /* initialize bmi270 device's acce and gyro sensor config*/
    bmi270_set_acce_gyr_init_config(&acce_init_cfg, &gyro_init_cfg, hdev);

    return hdev;
}

/* 用户根据实际情况将bmi270挂载到指定SPI总线，确定CS片选引脚 */
static int bmi270_attach_spi_bus(void)
{
    // 挂载SPI设备bmi270
    if (rt_hw_spi_device_attach(BMI270_SPI_BUSNAME, BMI270_SPI_DEVNAME, GPIOA, GPIO_PIN_4) != RT_EOK)
    {
        return -1;
    }
    return 0;
}
INIT_COMPONENT_EXPORT(bmi270_attach_spi_bus);

static rt_err_t bmi270_control(struct rt_sensor_device *sensor, int cmd, void *args)
{
    struct bmi2_dev *hdev = sensor->parent.user_data;
    int8_t result = RT_EOK;

    switch (cmd)
    {
    case RT_SENSOR_CTRL_GET_ID:
        *(rt_uint8_t *)args = hdev->chip_id;
        break;
    case RT_SENSOR_CTRL_SET_ODR:
        result = bmi270_set_odr(sensor, (rt_uint32_t)args & 0xffff);
        break;
    case RT_SENSOR_CTRL_SET_RANGE:
        result = bmi270_set_range(sensor, (rt_uint32_t)args);
        break;
    case RT_SENSOR_CTRL_SET_POWER:
        result = bmi270_set_pwr_mode(sensor, (rt_uint32_t)args & 0xff);
        break;
    case RT_SENSOR_CTRL_SET_MODE:
        result = bmi270_select_mode(sensor, (rt_uint32_t)args);
        break;
    case RT_SENSOR_CTRL_SELF_TEST:
        result = bmi270_self_test(sensor, (rt_uint32_t)args);
        break;
    default:
        return -RT_EINVAL;
    }
    return result;
}

static rt_size_t bmi270_fetch_data(struct rt_sensor_device *sensor, void *buf, rt_size_t len)
{
    if (sensor->config.mode == RT_SENSOR_MODE_FIFO)
    {
        return bmi270_read_fifo(sensor, buf, len);
    }

    return bmi270_read(sensor, buf, len);
}

static int8_t copy_sensor_data2_rtthread(struct rt_sensor_data *rt_data_dest, struct bmi2_sens_axes_data *sensor_data_origin)
{
    if (rt_data_dest == RT_NULL || sensor_data_origin == RT_NULL)
    {
        return RT_ERROR;
    }

    rt_data_dest->data.acce.x = sensor_data_origin->x;
    rt_data_dest->data.acce.y = sensor_data_origin->y;
    rt_data_dest->data.acce.z = sensor_data_origin->z;

    return RT_EOK;
}

static int8_t bmi270_read_fifo(struct rt_sensor_device *sensor, void *buf, rt_size_t len)
{
    int8_t rslt = RT_EOK;

    struct rt_sensor_data *data = buf;
    struct bmi2_fifo_frame bmi270_fifo_frame;
    struct bmi2_dev *hdev = sensor->parent.user_data;
    struct bmi2_sens_axes_data sens_fifo_data;
    struct bmi2_aux_fifo_data aux_data;

    rslt = bmi2_read_fifo_data(&bmi270_fifo_frame, hdev);
    if (rslt != RT_EOK)
    {
        rt_kprintf("bmi270_read_fifo--->bmi2_read_fifo_data failed\n");
        return rslt;
    }

    data->type = RT_SENSOR_CLASS_ACCE;
    data->timestamp = rt_tick_get();

    /* 加速度传感器 */
    if (sensor->info.type == RT_SENSOR_CLASS_ACCE)
    {
        rslt = bmi2_extract_accel(&sens_fifo_data, (uint16_t *)&len, &bmi270_fifo_frame, hdev);
        copy_sensor_data2_rtthread(data, &sens_fifo_data);
    }
    /* 陀螺仪 */
    else if (sensor->info.type == RT_SENSOR_CLASS_GYRO)
    {
        rslt = bmi2_extract_gyro(&sens_fifo_data, (uint16_t *)&len, &bmi270_fifo_frame, hdev);
        copy_sensor_data2_rtthread(data, &sens_fifo_data);
    }
    /* 地磁--AUX设备 */
    else if (sensor->info.type == RT_SENSOR_CLASS_MAG)
    {
        rslt = bmi2_extract_aux(&aux_data, (uint16_t *)&len, &bmi270_fifo_frame, hdev);
        /* 待后续补充 */
    }

    return rslt;
}

static int8_t bmi270_read(struct rt_sensor_device *sensor, struct rt_sensor_data *buf, rt_size_t len)
{
    int8_t rslt = RT_EOK;
    uint16_t temp_data = 0;

    struct bmi2_dev *hdev = sensor->parent.user_data;
    struct bmi2_sens_data bmi270_sensor_data;
    struct rt_sensor_data *rt_sensor_data_x = buf;

    /* 调用此函数获得加速度、陀螺仪、AUX、sensortime数据 */
    rslt = bmi2_get_sensor_data(&bmi270_sensor_data, hdev);
    if (rslt != BMI2_OK)
    {
        rt_kprintf("bmi270_read-->bmi2_get_sensor_data failed\n");
        return rslt;
    }

    if (sensor->info.type == RT_SENSOR_CLASS_ACCE)
    {
        rt_sensor_data_x->type = RT_SENSOR_CLASS_ACCE;
        rslt = bmi270_copy2_rtthread(rt_sensor_data_x, &bmi270_sensor_data);
    }
    else if (sensor->info.type == RT_SENSOR_CLASS_GYRO)
    {
        rt_sensor_data_x->type = RT_SENSOR_CLASS_GYRO;
        rslt = bmi270_copy2_rtthread(rt_sensor_data_x, &bmi270_sensor_data);
    }
    else if (sensor->info.type == RT_SENSOR_CLASS_MAG)
    {
        rt_sensor_data_x->type = RT_SENSOR_CLASS_MAG;
        rslt = bmi270_copy2_rtthread(rt_sensor_data_x, &bmi270_sensor_data);
    }
    else if (sensor->info.type == RT_SENSOR_CLASS_TEMP)
    {
        bmi2_get_temperature_data(&temp_data, hdev); /* bmi270的fifo帧没有温度数据 */
        rt_sensor_data_x->type = RT_SENSOR_CLASS_TEMP;

        bmi270_temp_from_digital_num((int32_t*)&rt_sensor_data_x->data.temp, temp_data);
    }
    return rslt;
}

static int8_t bmi270_copy2_rtthread(struct rt_sensor_data *dst, struct bmi2_sens_data *src)
{
    int8_t rslt = RT_EOK;
    uint16_t acce_resolution = 0; /* 加速度计读出数据需要除以分辨率得到实际加速度值 */
    float gyro_resolution = 0;    /* 陀螺仪读出数据需要除以分辨率得到实际角速度值 */

    switch (dst->type)
    {
    case RT_SENSOR_CLASS_ACCE:
        if (acce_init_cfg.cfg.acc.range == BMI2_ACC_RANGE_2G)
        {
            acce_resolution = BMI270_ACCE_2G_RESOLUTION;
        }
        else if (acce_init_cfg.cfg.acc.range == BMI2_ACC_RANGE_4G)
        {
            acce_resolution = BMI270_ACCE_4G_RESOLUTION;
        }
        else if (acce_init_cfg.cfg.acc.range == BMI2_ACC_RANGE_8G)
        {
            acce_resolution = BMI270_ACCE_8G_RESOLUTION;
        }
        else
        {
            acce_resolution = BMI270_ACCE_16G_RESOLUTION;
        }
        sensor_data_from_digital_num((int32_t*)&dst->data.acce.x, src->acc.x, acce_resolution, RT_SENSOR_CLASS_ACCE);
        sensor_data_from_digital_num((int32_t*)&dst->data.acce.y, src->acc.y, acce_resolution, RT_SENSOR_CLASS_ACCE);
        sensor_data_from_digital_num((int32_t*)&dst->data.acce.z, src->acc.z, acce_resolution, RT_SENSOR_CLASS_ACCE);
        break;

    case RT_SENSOR_CLASS_GYRO:
        if (gyro_init_cfg.cfg.gyr.range == BMI2_GYR_RANGE_125)
        {
            gyro_resolution = BMI270_GYRO_125DPS_RESOLUTION;
        }
        else if (gyro_init_cfg.cfg.gyr.range == BMI2_GYR_RANGE_250)
        {
            gyro_resolution = BMI270_GYRO_250DPS_RESOLUTION;
        }
        else if (gyro_init_cfg.cfg.gyr.range == BMI2_GYR_RANGE_500)
        {
            gyro_resolution = BMI270_GYRO_500DPS_RESOLUTION;
        }
        else if (gyro_init_cfg.cfg.gyr.range == BMI2_GYR_RANGE_1000)
        {
            gyro_resolution = BMI270_GYRO_1000DPS_RESOLUTION;
        }
        else
        {
            gyro_resolution = BMI270_GYRO_2000DPS_RESOLUTION;
        }
        sensor_data_from_digital_num((int32_t*)&dst->data.gyro.x, src->gyr.x, gyro_resolution, RT_SENSOR_CLASS_GYRO);
        sensor_data_from_digital_num((int32_t*)&dst->data.gyro.y, src->gyr.y, gyro_resolution, RT_SENSOR_CLASS_GYRO);
        sensor_data_from_digital_num((int32_t*)&dst->data.gyro.z, src->gyr.z, gyro_resolution, RT_SENSOR_CLASS_GYRO);
        break;

    case RT_SENSOR_CLASS_MAG:
        break;

    default:
        rslt = RT_ERROR;
        break;
    }

    dst->timestamp = rt_sensor_get_ts();

    return rslt;
}

/* 向RT-Thread驱动框架提供获取数据和控制命令的接口 */
static struct rt_sensor_ops bmi270_sensor_ops = {bmi270_fetch_data, bmi270_control};

static int8_t bmi270_sensor_register_acce(struct rt_sensor_config *cfg, void *hdev)
{
    int8_t rslt = RT_EOK;
    rt_sensor_t sensor_acce = RT_NULL;

    sensor_acce = rt_calloc(1, sizeof(struct rt_sensor_device));
    if (sensor_acce == RT_NULL)
    {
        return RT_ERROR;
    }
    sensor_acce->info.type = RT_SENSOR_CLASS_ACCE;
    sensor_acce->info.vendor = RT_SENSOR_VENDOR_BOSCH;
    sensor_acce->info.model = "bmi270_acce";
    sensor_acce->info.unit = RT_SENSOR_UNIT_MG;          // 单位MG 毫G
    sensor_acce->info.intf_type = RT_SENSOR_INTF_SPI;    // SPI接口
    sensor_acce->info.range_max = BMI270_ACCE_MAX_RANGE; // 最大量程正负16g
    sensor_acce->info.range_min = BMI270_ACCE_MIN_RANGE; // 最小量程正负2g
    sensor_acce->info.period_min = BMI270_ACCE_MIN_PERIOD_MS_RT;
    sensor_acce->info.fifo_max = BMI270_ACCE_FIFO_BUF_MIN;

    rt_memcpy(&sensor_acce->config, cfg, sizeof(struct rt_sensor_config));
    sensor_acce->ops = &bmi270_sensor_ops;

    rslt = rt_hw_sensor_register(sensor_acce, BMI270_DEVICE_NAME, RT_DEVICE_FLAG_RDWR, hdev);
    if (rslt != RT_EOK)
    {
        rt_kprintf("BMI270 regist acce failed\n");
        return rslt;
    }
    rt_kprintf("BMI270 regist acce success\n");

    rslt = bmi2_set_accel_offset_comp(BMI2_ENABLE, hdev); /* 启用加速度偏移补偿 */
    return rslt;
}

static int8_t bmi270_sensor_register_gyro(struct rt_sensor_config *cfg, void *hdev)
{
    int8_t rslt = RT_EOK;
    rt_sensor_t sensor_gyro = RT_NULL;

    sensor_gyro = rt_calloc(1, sizeof(struct rt_sensor_device));
    if (sensor_gyro == RT_NULL)
        return RT_ERROR;

    sensor_gyro->info.type = RT_SENSOR_CLASS_GYRO;
    sensor_gyro->info.vendor = RT_SENSOR_VENDOR_BOSCH;
    sensor_gyro->info.model = "bmi270_gyro";
    sensor_gyro->info.unit = RT_SENSOR_UNIT_MDPS; /* bmi270陀螺仪量程在125~2000dps，这里设置单位为mdps */
    sensor_gyro->info.intf_type = RT_SENSOR_INTF_SPI;
    sensor_gyro->info.range_max = BMI270_GYRO_MAX_RANGE;
    sensor_gyro->info.range_min = BMI270_GYRO_MIN_RANGE;
    sensor_gyro->info.period_min = BMI270_GYRO_MIN_PERIOD_MS_RT;
    sensor_gyro->info.fifo_max = BMI270_GYRO_FIFO_BUF_MIN;

    rt_memcpy(&sensor_gyro->config, cfg, sizeof(struct rt_sensor_config));
    sensor_gyro->ops = &bmi270_sensor_ops;

    rslt = rt_hw_sensor_register(sensor_gyro, BMI270_DEVICE_NAME, RT_DEVICE_FLAG_RDWR, hdev);
    if (rslt != RT_EOK)
    {
        rt_kprintf("BMI270 regist gyroscope failed\n");
        return rslt;
    }
    rt_kprintf("BMI270 regist gyroscope success\n");

    rslt = bmi2_set_gyro_offset_comp(BMI2_ENABLE, hdev); /* 启用陀螺仪偏移补偿 */
    return rslt;
}

static int8_t bmi270_sensor_register_temp(struct rt_sensor_config *cfg, void *hdev)
{
    int8_t rslt = RT_EOK;
    rt_sensor_t sensor_temp = RT_NULL;

    sensor_temp = rt_calloc(1, sizeof(struct rt_sensor_device));
    if (sensor_temp == RT_NULL)
        return RT_NULL;

    sensor_temp->info.type = RT_SENSOR_CLASS_TEMP;
    sensor_temp->info.vendor = RT_SENSOR_VENDOR_BOSCH;
    sensor_temp->info.model = "bmi270_temp";
    sensor_temp->info.unit = RT_SENSOR_UNIT_DCELSIUS; /* 单位0.1°C */
    sensor_temp->info.intf_type = RT_SENSOR_INTF_SPI;
    sensor_temp->info.range_max = BMI270_TEMP_MAX_RANGE;
    sensor_temp->info.range_min = BMI270_TEMP_MIN_RANGE;
    sensor_temp->info.period_min = BMI270_TEMP_MIN_PERIOD_MS_RT;
    sensor_temp->info.fifo_max = 0;

    rt_memcpy(&sensor_temp->config, cfg, sizeof(struct rt_sensor_config));
    sensor_temp->ops = &bmi270_sensor_ops;

    rslt = rt_hw_sensor_register(sensor_temp, BMI270_DEVICE_NAME, RT_DEVICE_FLAG_RDWR, hdev);
    if (rslt != RT_EOK)
    {
        rt_kprintf("BMI270 regist tempereture failed\n");
        return rslt;
    }
    rt_kprintf("BMI270 regist tempereture success\n");

    return rslt;
}

static int8_t bmi270_sensor_register(struct rt_sensor_config *cfg, void *hdev)
{
    /* bmi270_sensor_enable 根据指定的传感器序列启用不同的传感器 */
    int8_t rslt = RT_EOK;

#ifdef BMI270_USING_ACCE
    rslt = bmi270_sensor_register_acce(cfg, hdev);
    if (rslt != RT_EOK)
    {
        rt_kprintf("bmi270_sensor_register_acce failed\n");
    }
#endif

#ifdef BMI270_USING_GYRO
    rslt = bmi270_sensor_register_gyro(cfg, hdev);
    if (rslt != RT_EOK)
    {
        rt_kprintf("bmi270_sensor_register_gyro failed\n");
    }
#endif

#ifdef BMI270_USING_AUX
    if (sg_aux_ctrl_fcn._bmi270_sensor_register_aux_)
    {
        rslt = (sg_aux_ctrl_fcn._bmi270_sensor_register_aux_)(cfg, hdev);
    }
    if (rslt != RT_EOK)
    {
        rt_kprintf("bmi270_sensor_register_aux failed\n");
    }
#endif

#ifdef BMI270_USING_TEMP
    rslt = bmi270_sensor_register_temp(cfg, hdev);
    if (rslt != RT_EOK)
    {
        rt_kprintf("bmi270_sensor_register_temp failed\n");
    }
#endif

    return rslt;
}

static int8_t bmi270_set_odr(rt_sensor_t sensor, rt_uint16_t odr)
{
    /* 调用 bmi270_set_sensor_config 改变ODR */
    int8_t rslt = RT_EOK;

    struct bmi2_dev *hdev = sensor->parent.user_data;
    struct bmi2_sens_config sensor_config;
    uint8_t set_odr = find_bmi270_odr(sensor->info.type, odr);

    if (sensor->info.type == RT_SENSOR_CLASS_ACCE)
    {
        sensor_config.type = BMI2_ACCEL;
        bmi270_get_sensor_config(&sensor_config, 1, hdev);
        sensor_config.cfg.acc.odr = set_odr;
    }
    else if (sensor->info.type == RT_SENSOR_CLASS_GYRO)
    {
        sensor_config.type = BMI2_GYRO;
        bmi270_get_sensor_config(&sensor_config, 1, hdev);
        sensor_config.cfg.gyr.odr = set_odr;
    }
    else if (sensor->info.type == RT_SENSOR_CLASS_MAG)
    {
        sensor_config.type = BMI2_AUX;
        bmi270_get_sensor_config(&sensor_config, 1, hdev);
        sensor_config.cfg.aux.odr = set_odr;
    }
    else if (sensor->info.type == RT_SENSOR_CLASS_TEMP)
    {
        /* 温度不调用bmi270_set_sensor_config更改ODR，直接使用寄存器
           如果陀螺仪已启用(即PWR_CTRL.gyr_en=0b01)，
           温度传感器将以100 Hz +/-12%的更新速率自动启用,
           如果陀螺仪已禁用，以0.78 Hz的更新速率输出温度
        */
        if (odr == BMI270_TEMP_SENSOR_ODR_HIGH_100HZ)
        {
            uint8_t sens_list[1] = {BMI2_GYRO};
            bmi270_sensor_enable(sens_list, sizeof(sens_list), hdev); /* 启用陀螺仪 */
        }
        else if (odr == BMI270_TEMP_SENSOR_ODR_LOW_0P78HZ)
        {
            uint8_t sens_list[1] = {BMI2_GYRO};
            bmi270_sensor_disable(sens_list, sizeof(sens_list), hdev); /* 禁用陀螺仪 */
        }
    }
    bmi270_set_sensor_config(&sensor_config, 1, hdev);
    return rslt;
}

static int8_t bmi270_set_range(rt_sensor_t sensor, rt_uint16_t range)
{
    /* 调用 bmi270_set_sensor_config 改变range */

    int8_t rslt = RT_EOK;

    struct bmi2_dev *hdev = sensor->parent.user_data;
    struct bmi2_sens_config sensor_config;
    uint8_t set_range = find_bmi270_range(sensor->info.type, range);

    if (sensor->info.type == RT_SENSOR_CLASS_ACCE)
    {
        sensor_config.type = BMI2_ACCEL;
        bmi270_get_sensor_config(&sensor_config, 1, hdev);
        sensor_config.cfg.acc.range = set_range;
    }
    else if (sensor->info.type == RT_SENSOR_CLASS_GYRO)
    {
        sensor_config.type = BMI2_GYRO;
        bmi270_get_sensor_config(&sensor_config, 1, hdev);
        sensor_config.cfg.gyr.range = set_range;
    }
    else if (sensor->info.type == RT_SENSOR_CLASS_MAG)
    {
    }
    else if (sensor->info.type == RT_SENSOR_CLASS_TEMP)
    {
        /* 温度不调用bmi270_set_sensor_config更改range，直接使用寄存器
           温度范围在-40°~+85°
        */
    }
    bmi270_set_sensor_config(&sensor_config, 1, hdev);

    return rslt;
}

static int8_t bmi270_set_pwr_mode(rt_sensor_t sensor, rt_uint8_t pwr_mode)
{
    /* bmi270_sensor_enable 通过使能指定的传感器修改供电模式 */

    int8_t rslt = RT_EOK;
    struct bmi2_dev *hdev = sensor->parent.user_data;
    //    struct bmi2_sens_config sensor_config;

    switch (pwr_mode)
    {
    case RT_SENSOR_POWER_DOWN:
        rslt = bmi270_sensor_disable(sense_list, sizeof(sense_list), hdev);
        break;

    case RT_SENSOR_POWER_NORMAL:
        rslt = bmi270_sensor_enable(sense_list, sizeof(sense_list), hdev);
        rslt = bmi2_set_adv_power_save(BMI2_DISABLE, hdev);
        break;

    case RT_SENSOR_POWER_LOW:
        rslt = bmi270_sensor_enable(sense_list, sizeof(sense_list), hdev);
        rslt = bmi2_set_adv_power_save(BMI2_ENABLE, hdev);
        break;

    default:
        break;
    }

    return rslt;
}

static int8_t bmi270_select_mode(rt_sensor_t sensor, rt_uint8_t rx_mode)
{
    /* bmi2_set_int_pin_config设置数据接收中断引脚 */
    //    int8_t rslt = RT_EOK;
    struct bmi2_dev *hdev = sensor->parent.user_data;
    //    struct bmi2_int_pin_config int_pin_cfg;

    /* 非锁存中断是为使用边缘触发中断的系统设计的，
       锁存中断是为使用水平触发中断的系统设计的。
    */
    if (rx_mode == RT_SENSOR_MODE_FIFO)
    {
        // int_pin_cfg.pin_type = BMI270_FIFO_FULL_INT_PIN;
        // int_pin_cfg.int_latch = BMI2_INT_NON_LATCH;
        // int_pin_cfg.pin_cfg->input_en = BMI2_DISABLE;
        // int_pin_cfg.pin_cfg->lvl = BMI270_INT_PIN_ACTIVE_HIGH;
        // int_pin_cfg.pin_cfg->od = BMI2_INT_PUSH_PULL; /* 推挽输出 */
        // int_pin_cfg.pin_cfg->output_en = BMI2_ENABLE;

        // bmi2_set_int_pin_config(&int_pin_cfg, hdev);

        /* 调用bmi2_set_fifo_config设置fifo帧格式 */
        /* 这里重点是FIFO帧有帧头，以及AUX、加速度、陀螺仪数据 */
        uint16_t fifo_config = 0;
        fifo_config |= FIFO_HAS_HEAD;
#ifdef BMI270_USING_ACCE
        fifo_config |= FIFO_HAS_ACCE;
#endif
#ifdef BMI270_USING_GYRO
        fifo_config |= FIFO_HAS_GYRO;
#endif
#ifdef BMI270_USING_AUX
        fifo_config |= FIFO_HAS_AUX;

        // 设置fifo有8字节的aux信息
        uint8_t aux_if;
        bmi2_get_regs(BMI2_AUX_IF_CONF_ADDR, &aux_if, 1, hdev);
        aux_if = aux_if | (0x03);
#endif
        /* 参见bmi270数据手册 */
        bmi2_set_fifo_config(fifo_config, BMI2_ENABLE, hdev);
    }

    return RT_EOK;
}

static int8_t bmi270_self_test(rt_sensor_t sensor, rt_uint8_t no_use)
{
    /* bmi2_perform_accel_self_test进行加速度自检 */
    /* bmi2_do_gyro_st进行陀螺仪自检 */
    int8_t rslt1 = RT_EOK;
    int8_t rslt2 = RT_EOK;
    struct bmi2_dev *hdev = sensor->parent.user_data;

    rslt1 = bmi2_perform_accel_self_test(hdev);
    rslt2 = bmi2_do_gyro_st(hdev);
    if (rslt1 != RT_EOK)
    {
        rt_kprintf("bmi270_self_test acce failed\n");
        return RT_ERROR;
    }

    if (rslt2 != RT_EOK)
    {
        rt_kprintf("bmi270_self_test gyro failed\n");
        return RT_ERROR;
    }

    rt_kprintf("bmi270_self_test success\n");
    return RT_EOK;
}

static int8_t sensor_data_from_digital_num(int32_t *sensor_data, int32_t digital_num, float resolution, uint8_t sensor_type)
{
    float val = digital_num;
    val /= resolution;

    switch (sensor_type)
    {
    case RT_SENSOR_CLASS_ACCE: /* RT-Thread加速度单位mg */
        val *= 1000;
        break;
    case RT_SENSOR_CLASS_GYRO: /* RT-Thread角速度单位mdps */
        val *= 1000;
        break;
    case RT_SENSOR_CLASS_TEMP:
        val *= 10; /* RT-Thread温度单位0.1°C */
        break;
    default:
        return RT_ERROR;
        break;
    }

    *sensor_data = val;
    return RT_EOK;
}

static int8_t bmi270_temp_from_digital_num(int32_t *sensor_data, uint16_t digital_num)
{
    /* bmi270计算温度参见数据手册，按照：
            0x8001 ---> -(41-1/2^9)
            0x8002 ---> -(41-1/2^9 * 2)
            0x8003 ---> -(41-1/2^9 * 3)
            ...
            0xffff ---> -(41-1/2^9 * 32767)
            0x0000 ---> 23
            0x0001 ---> 23 + 1/2^9
            ...
            0x7fff ---> 87-1/2^9
    */
    if (digital_num == 0x8000)
        return RT_ERROR;

    float temp_val = 0;

    if (digital_num >= 0x8001 && digital_num <= 0xffff)
    {
        temp_val = 1 / (2 ^ 9 * (digital_num - 0x8000));
        temp_val = -(41 - temp_val);
    }
    else if (digital_num >= 0x0000 && digital_num <= 0x7fff)
    {
        temp_val = 1 / (2 ^ 9 * (digital_num - 0x0000));
        temp_val = 23 + temp_val;
    }

    temp_val *= 10; /* RT-Thread温度传感器单位是0.1°C */
    *sensor_data = temp_val;

    return RT_EOK;
}

static void bmi270_sensor_sample(void)
{
    rt_device_t dev = RT_NULL;
    struct rt_sensor_data data;
    rt_size_t i;

    /* read bmi270 device acce sensor */
    dev = rt_device_find("acce_bmi270");
    if (dev == RT_NULL)
    {
        rt_kprintf("Can't find acce_bmi270 device\n");
        return;
    }

    for (i = 0; i < 5; i++)
    {
        /* 从传感器读取一个数据 */
        rt_device_read(dev, 0, &data, 1);
        sensor_show_data((rt_sensor_t)dev, &data);
        rt_thread_mdelay(100);
    }

    /* read bmi270 device gyro sensor */
    dev = rt_device_find("gyro_bmi270");
    if (dev == RT_NULL)
    {
        rt_kprintf("Can't find acce_bmi270 device\n");
        return;
    }

    for (i = 0; i < 5; i++)
    {
        /* 从传感器读取一个数据 */
        rt_device_read(dev, 0, &data, 1);
        sensor_show_data((rt_sensor_t)dev, &data);
        rt_thread_mdelay(100);
    }

    /* read bmi270 device temp sensor */
    dev = rt_device_find("temp_bmi270");
    if (dev == RT_NULL)
    {
        rt_kprintf("Can't find acce_bmi270 device\n");
        return;
    }

    for (i = 0; i < 5; i++)
    {
        /* 从传感器读取一个数据 */
        rt_device_read(dev, 0, &data, 1);
        sensor_show_data((rt_sensor_t)dev, &data);
        rt_thread_mdelay(100);
    }
}
MSH_CMD_EXPORT(bmi270_sensor_sample, bmi270_device_sample);
